package com.xiaomo.gitee.datamanager.security.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaomo.gitee.datamanager.aspect.log.anno.SysLog;
import com.xiaomo.gitee.datamanager.dto.security.TokenDTO;
import com.xiaomo.gitee.datamanager.dto.security.UserDTO;
import com.xiaomo.gitee.datamanager.entity.Role;
import com.xiaomo.gitee.datamanager.common.exception.UsernameExistedException;
import com.xiaomo.gitee.datamanager.mapper.*;
import com.xiaomo.gitee.datamanager.entity.Permission;
import com.xiaomo.gitee.datamanager.entity.User;
import com.xiaomo.gitee.datamanager.entity.UserRole;
import com.xiaomo.gitee.datamanager.security.service.UserService;
import com.xiaomo.gitee.datamanager.util.JwtUtils;
import lombok.RequiredArgsConstructor;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService {

    private final UserMapper userMapper;
    private final UserRoleMapper userRoleMapper;
    private final RolePermMapper rolePermMapper;
    private final PermissionMapper permissionMapper;
    private final RoleMapper roleMapper;
    private final AuthenticationConfiguration authenticationConfiguration;

    private final JwtUtils jwtUtils;

    private final PasswordEncoder passwordEncoder;
    private final Role defaultRole;

    @Override
    @SysLog("用户被删除")
    public boolean deleteUser(String username) {
        User user = userMapper.selectOneByUsername(username);
        if (user == null) {
            return false;
        }
        userRoleMapper.deleteByUserId(user.getId());
        userMapper.deleteByUsername(username);

        MDC.put("被删除用户名",username);

        return true;
    }

    @Override
    @SysLog("用户注册")
    public void register(UserDTO userDTO) throws UsernameExistedException {
        String username = userDTO.getUsername();
        String password = userDTO.getPassword();
        if (userMapper.selectOneByUsername(username) != null) {
            throw new UsernameExistedException();
        }
        User user = new User(username, passwordEncoder.encode(password), 1);
        userMapper.insert(user);
        user = userMapper.selectOneByUsername(username);
        userRoleMapper.insert(new UserRole(user.getId(),defaultRole.getId()));

        MDC.put("注册用户名",username);
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userMapper.selectOneByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("用户名未找到");
        }
        user.setAuthorities(getUserAuthorityById(user.getId()));
        return user;
    }

    @SysLog("用户通过API登录")
    public TokenDTO login(UserDTO user) throws Exception {
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(user.getUsername(),user.getPassword());
        Authentication authentication = authenticationConfiguration.getAuthenticationManager().authenticate(usernamePasswordAuthenticationToken);
        if (authentication == null) {
            throw new AuthenticationServiceException("登录失败");
        }//
        TokenDTO tokenDTO = new TokenDTO();
        tokenDTO.setToken(jwtUtils.generateJwt(String.valueOf(userMapper.selectOneByUsername(user.getUsername()).getId())));
        tokenDTO.setValidTime(jwtUtils.getExpire() / 3600 / 24);
        tokenDTO.setRole(roleMapper.selectOneById(userRoleMapper.selectByUserId(userMapper.selectOneByUsername(authentication.getName()).getId()).getRoleId()).getDescription());

        MDC.put("登录用户名",user.getUsername());

        return tokenDTO;
    }

    public List<GrantedAuthority> getUserAuthorityById(long id) {
        User user = userMapper.selectOneById(id);
        Role role = roleMapper.selectOneById(userRoleMapper.selectByUserId(user.getId()).getRoleId());
        if (role == null ) {
            return new ArrayList<>();
        }
        List<Role> actualRoles = new ArrayList<>(Collections.singletonList(role));
        while (role.getInherit() != null) {
            role = roleMapper.selectOneById(role.getInherit());
            actualRoles.add(role);
        }
        List<String> permissions = new ArrayList<>();
        actualRoles.forEach(userRole -> {
            permissions.add("ROLE_" + userRole.getName());
            rolePermMapper.selectByRoleId(userRole.getId()).forEach(rolePerm -> {
                String permName = permissionMapper.selectOneById(rolePerm.getPermId()).getName();
                if (!permissions.contains(permName)) {
                    permissions.add(permName);
                }
            });
        });
        return AuthorityUtils.createAuthorityList(permissions);
    }

}




